﻿﻿
using System;

public class ByteArray
{
    // 默认大小
    const int DEFAULT_SIZE = 1024;
    const int MAX_SIZE = 500 * 1024; // 最大缓存容量

    // 初始大小
    int initSize = 0;

    // 容量
    private int capacity = 0;
    // 剩余空间
    public int remain { get { return capacity - writeIdx; } }

    // 缓冲区
    public byte[] bytes;
    // 读写位置
    public int readIdx = 0;
    public int writeIdx = 0;

    // 数据长度
    public int length { get { return writeIdx - readIdx; } }

    // 构造函数
    public ByteArray(byte[] defaultBytes)
    {
        bytes = defaultBytes;
        readIdx = 0;
        writeIdx = defaultBytes.Length;
        capacity = defaultBytes.Length;
        initSize = defaultBytes.Length;
    }

    public ByteArray(int size = DEFAULT_SIZE)
    {
        bytes = new byte[size];
        capacity = size;
        initSize = size;
        readIdx = 0;
        writeIdx = 0;
    }

    public void Resize(int size)
    {
        // BdUtils.assert(size <= MAX_SIZE, $"*** Error: size[{size}]超出最大缓存容量MAX_SIZE[{MAX_SIZE}]!");

        if (size < initSize) return;
        if (size < length) return;
        int n = 1;
        while (n < size) n *= 2;

        capacity = n < MAX_SIZE ? n : MAX_SIZE;

        byte[] newBytes = new byte[capacity];
        Array.Copy(bytes, readIdx, newBytes, 0, writeIdx - readIdx);
        bytes = newBytes;
        writeIdx = length;
        readIdx = 0;
    }

    public void CheckAndMoveBytes()
    {
        if (length < 8)
        {
            MoveBytes();
        }
    }
    public void MoveBytes()
    {
        if (length > 0)
        {
            Array.Copy(bytes, readIdx, bytes, 0, length);
        }
        writeIdx = length;
        readIdx = 0;
    }

    // 写入数据
    public int Write(byte[] bs, int offset, int count)
    {
        if (remain < count)
        {
            Resize(length + count);
        }
        Array.Copy(bs, offset, bytes, writeIdx, count);
        writeIdx += count;
        return count;
    }

    // 读取数据
    public int Read(byte[] bs, int offset, int count)
    {
        count = Math.Min(count, length);
        Array.Copy(bytes, readIdx, bs, offset, count);
        readIdx += count;
        CheckAndMoveBytes();
        return count;
    }

    // 读取int16
    public Int16 ReadInt16()
    {
        if (length < 2) return 0;
        Int16 ret = (Int16)((bytes[readIdx + 1] << 8 | bytes[readIdx]));
        // if (add_read_index)  // 读入成功了就前移readIdx
        readIdx += 2;
        CheckAndMoveBytes();
        return ret;
    }
    // 读取int
    public Int32 ReadInt32()
    {
        if (length < 4) return 0;
        Int32 ret = (Int32)(
            (bytes[readIdx + 3] << 24) |
            (bytes[readIdx + 2] << 16) |
            (bytes[readIdx + 1] << 8) |
            (bytes[readIdx + 0])
            );
        readIdx += 4;
        CheckAndMoveBytes();
        return ret;
    }

    // 打印缓冲区(debug用)
    public override string ToString()
    {
        // BdUtils.log($"ByteArray: readIdx[{readIdx}], length[{length}], writeIdx[{writeIdx}], capacity[{capacity}], remain[{remain}]");
        // return BitConverter.ToString(bytes, readIdx, length);
        string info = $"ByteArray: readIdx[{readIdx}], length[{length}], writeIdx[{writeIdx}], capacity[{capacity}], remain[{remain}]";
        return info;
    }

    // 打印调试信息
    public void Debug(int i = 0)
    {
        // var s = string.Format(
        //     "readIdx({0}) | writeIdx({1}) | bytes({2})", readIdx, writeIdx, BitConverter.ToString(bytes, 0, bytes.Length)
        //     );
        BdUtils.log($"\n--- Debug ByteArray[{i}] ---");
        BdUtils.log(this.ToString());
        BdUtils.log($"bytes --- {BitConverter.ToString(bytes, 0, bytes.Length)}");
    }
}

namespace AppByteArray
{
    public class MyClient
    {
        // static bool done = false;
        public static void run()
        {
            BdUtils.log("--- MyClient.run!");
            var cls = new ByteArray(5);
            // cls.Debug(1);

            // write bytes
            byte[] wb = new byte[] { 0, 1, 1, 1, 2, 1 };
            cls.Write(wb, 0, wb.Length);
            cls.Debug(2);

            // 每次读前两位, 例如[0, 1, 1, 1, 2, 1]就是[256, 257, 258]
            BdUtils.log("cls.ReadInt16()", cls.ReadInt16());
            BdUtils.log("cls.ReadInt16()", cls.ReadInt16());
            BdUtils.log("cls.ReadInt16()", cls.ReadInt16());

            // // read bytes
            // byte[] rb = new byte[4];
            // cls.Read(rb, 0, 2);
            // cls.Debug(3);
            // BdUtils.log("3 rb --- ", BitConverter.ToString(rb));

            // // write bytes with resize
            // wb = new byte[] { 6, 7, 8, 9, 10, 11 };
            // cls.Write(wb, 0, wb.Length);
            // cls.Debug(4);
        }

    }
}